#ifndef PACKET_H
#define PACKET_H

#include <QtCore>
#include <QSharedPointer>

namespace Network {

/**
 * @brief Reprezentacja pakietu wykorzystywanego do komunikacji sieciowej.
 *
 * Zawiera trzy główne pola (id, client_id, size) oraz dynamiczną tablicę
 * przechowującą właściwe dane pakietu. Zapis i odczyt danych pakietu
 * możliwy jest przy pomocy zdefiniowanych operatorów strumieniowych.
 *
 * Przed wysyłką każdy pakiet jest pakowany (nagłówek jest dołaczany na początku danych)
 *
 * @par Rodzaje pakietów
 *
 *
 **/
struct Packet
{
	/**
	 * Typ pakietu
	 **/
	enum Type {
		/// znajdź pliki o danej nazwie i atrybutach
		ptFind		= 1,
		/// lista plików spełniających kryteria
		ptList		= 2,
		/// wyślij listę klientów posiadających dany plik
		ptFindSeeds	= 3,
		/// lista aktywnych klientów posiadających dany plik
		ptListSeeds	= 4,
		/// żądanie fragmentu pliku
		ptGet		= 5,
		/// wysłanie fragmentu pliku
		ptGive		= 6,
		/// rejestracja nowego klienta
		ptIDRequest	= 7,
		/// pakiet powitalny dla nowego klienta
		ptNewID		= 8,
		/// logowanie klienta
		ptLogin		= 9,
		/// wylogowanie klienta
		ptLogout	= 10,
		/// pakiet informacyjny od serwera
		ptInfo		= 11,
		/// lista ze zmianami plików posiadanych przez użytkownika
		/// zawiera informacje o nowych, zmienionych oraz usuniętych plikach
		ptFileList	= 12

	}; 


	/// identyfikator pakietu
	int id;

	/// identyfikator klienta
	int client_id;

	/// całkowity rozmiar pakietu
	int size;

	/**
	 * dane specyficzne dla danego pakietu
	 **/
	const char * data();

	/**
	 * Ustawienie w pakiecie danych odebranych z sieci
	 **/
	void data(char * buf, int size);

	/**
	 * Pakowanie nagłówka oraz danych
	 **/
	void pack();

	/**
	 * Rozpakowanie danych
	 **/
	void unpack();

	/**
	 * Konstruktor
	 **/
	Packet();

	/**
	 * Kopiowanie pakietu
	 **/
	Packet(const Packet & packet);

	/**
	 * Usuwanie pakietu
	 **/
	~Packet();

	/**
	 * Tekstowa forma pakietu wykorzystywana do celów testowych
	 **/
	QString dump();


	/**
	 * Ustawienie pozycji odczytu
	 **/
	void seek(int offset, int mode);

	int innerSize() {
		return ba.size();
	}

	/**
	 * Dopisanie liczby do pakietu
	 **/
	Packet & operator << (int i);

	/**
	 * Dopisanie napisu do pakietu
	 **/
	Packet & operator << (const QString & s);

	/**
	 * Dopisanie tablicy bajtów do pakietu
	 **/
	Packet & operator << (const QByteArray & b);



	/**
	 * Odczytanie liczby z pakietu
	 **/
	Packet & operator >> (int & i);

	/**
	 * Odczytwanie napisu z pakietu
	 **/
	Packet & operator >> (QString & s);

	/**
	 * Odczytwanie tablicy bajtów z pakietu
	 **/
	Packet & operator >> (QByteArray & b);

	int baSize() {
		return ba.size();
	}

private:
	/// aktualna pozycja znacznika odczytu
	int pos_;

	/// wewnętrzna tablica przechowująca dane
	QByteArray ba;

	/// czy do tablicy bajtów zapakowany został nagłówek
	bool packed;
};

} // namespace Network


#endif // PACKET_H
